﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "GmStructure.h"

#include "DbDataSchema.h"
#include "IElementShapeHandleBehavior.h"
#include "IElementMoveContext.h"
#include "NdbObjectSchematic.h"
#include "IDocument.h"
#include "IElementTransformationComponent.h"
#include "IElementCopyPasteComponent.h"
#include "IElementParametersCustomizer.h"
#include "IElementPositionPoints.h"
#include "IElementViewSpecificShapeComponent.h"
#include "IElementUiManipulatorComponent.h"
#include "IElementShapeHandleBehavior.h"
#include "WeakPtr.h"

namespace gcmp 
{
    class IStructureSlopeLine;
    class IElementShapeHandle;
    class IGraphicsElementShape;

    // 视图相关行为
    class StructureSlopeLineViewSpecificShapeComponent : public NdbObjectSchematic, 
        public IElementViewSpecificShapeComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, StructureSlopeLineViewSpecificShapeComponent, gcmp::NdbObjectSchematic, 02DA8C1B - 06DC - 4F23 - A040 - 3578F84C4500, gmstructure, IElementViewSpecificShapeComponent)
            DATA(OwnerPtr<IRenderPriorityOffsetProvider>, RenderPriorityOffsetProvider)
            DATA_TRANSIENT(IElement*, pOwnerElement)
            DATA(OwnerPtr<IGraphicsNodeVisibilityCustomizer>, GraphicsNodeVisibilityCustomizer)
        DBOBJECT_DATA_END
    public:
        virtual ~StructureSlopeLineViewSpecificShapeComponent() {}

        virtual bool SetOwnerElement(IElement* pOwnerElement) override;
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
    public:
        virtual bool IsVisibleInModelView(const IModelView* pModelView) const override;
        virtual OwnerPtr<IGraphicsElementShape> CreateViewSpecificElementShape(const IModelView* pModelView) const override;
        virtual bool IsCuttableByModelViewRange(const IModelView* pModelView) const override { return false; }
        virtual void ReportDependentElements(std::vector<ElementId>& dependentElementIds) const override {};

        virtual void SetRenderPriorityOffsetProvider(OwnerPtr<IRenderPriorityOffsetProvider> opProvider) override;
        virtual const IRenderPriorityOffsetProvider* GetRenderPriorityOffsetProvider() const override;
        virtual IRenderPriorityOffsetProvider* GetRenderPriorityOffsetProvider() override;

        virtual void SetGraphicsNodeVisibilityCustomizer(OwnerPtr<IGraphicsNodeVisibilityCustomizer> opCustomizer) override;
        virtual const IGraphicsNodeVisibilityCustomizer* GetGraphicsNodeVisibilityCustomizer() const override;
        virtual IGraphicsNodeVisibilityCustomizer* GetGraphicsNodeVisibilityCustomizer() override;
    };


    // 移动、旋转行为
    class StructureSlopeLineTransformationComponent : public NdbObjectSchematic, public IElementTransformationComponent
    {
        DBOBJECT_DATA_BEGIN(gcmp, StructureSlopeLineTransformationComponent, gcmp::NdbObjectSchematic, A28739C1 - 006C - 4D73 - 8854 - F5F0DBB82E00, gmstructure)
        DBOBJECT_DATA_END
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement.Get(); }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement.Get(); }

        virtual bool CanBeMoved(std::wstring* explanation = nullptr) const override;
        virtual bool Translate(const IElementMoveContext& moveContext) override;

        virtual bool CanBeRotated(std::wstring* explanation = nullptr) const override;
        virtual bool Rotate(const Vector3d& pointOnVec, const Vector3d& rotateDir, double rotateAngle) override;

        virtual bool CanBeScaled(std::wstring* explanation = nullptr) const override { return false; }
        virtual bool Scale(const Vector3d& basePt, float scaleFactor) override { return false; }

        virtual bool Transform(const Matrix4d& matrix) override;
    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return  nullptr;
        }
    private:
        WeakPtr<IElement> m_pOwnerElement;
    };

    // 拷贝粘贴行为
    class StructureSlopeLineCopyPasteComponent : public NdbObjectSchematic, public IElementCopyPasteComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp,StructureSlopeLineCopyPasteComponent, gcmp::NdbObjectSchematic, E1B310E6 - D060 - 4A73 - 966A - 76B9D5C3ABC2, gmstructure, IElementCopyPasteComponent)
        DBOBJECT_DATA_END
    public:
        StructureSlopeLineCopyPasteComponent(IElement* pElement);

        virtual OwnerPtr<IPasteHelper> GetPasteHelper() const override { return nullptr; }

        virtual void UpdateAfterCopy(const ICopyContext& copyContext) override {}

        virtual void UpdateForWeakParentCopied(const IDocument* pDocFrom, const IElement* pSource, const IElement* pCopy) const override {}

        virtual bool ShouldBeCopiedTogether(const ICopyContext & copyContext) const override { return true; }

        virtual bool IsStrongParentsNeedCopied() const override { return false; }

        virtual bool CanBeCopied(std::wstring* pErrorMessage) const override;

    public:
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }

        // 辅助方法
        IDocument* GetDocument() const;
        ElementId GetOwnerElementId() const;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        IElement* m_pOwnerElement;
    };

    // 拷贝策略问题
    class StructureSlopeLineCopyStrategyComponent : public NdbObjectSchematic, public IElementCopyStrategyComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, StructureSlopeLineCopyStrategyComponent, gcmp::NdbObjectSchematic, 9BFEEFD5 - F303 - 482B - A4F7 - 46C9A05F3B88, gmstructure, IElementCopyStrategyComponent)
        DBOBJECT_DATA_END
    public:
        virtual void Report(const gcmp::ICopyContext & copyContext, gcmp::ICopyStrategyReporter& reporter) const override;

    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

        // 辅助方法
        IDocument* GetDocument() const;
        ElementId GetOwnerElementId() const;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
    private:
        IElement* m_pOwnerElement;
    };

    // 参数行为
    class StructureSlopeLineParametersCustomizer : public NdbObjectSchematic, public IElementParametersCustomizer
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, StructureSlopeLineParametersCustomizer, gcmp::NdbObjectSchematic, D98903AA-382E-4A40-8F59-1C78B4200792, gmstructure, IElementParametersCustomizer)
        DBOBJECT_DATA_END
    public:
        explicit StructureSlopeLineParametersCustomizer(IElement* pOwnerElement)
            : m_pOwnerElement(pOwnerElement)
        {
        }

        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement.Get(); }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement.Get(); }

        virtual OwnerPtr<IParameter> GetNativeParameter(int paramDefId) const override;
        virtual bool SetNativeParameter(const IParameter *param, std::wstring* errorMsg) override;
        virtual void ReportParameterDefinitions(std::vector<int>* pParamDefIds) const override;
        virtual bool IsParameterModifiable(int parameterId) const override;
        virtual bool IsPresetParameter(const UniIdentity& paramDefUid) const override { return true; }
        virtual void FilterParameterValues(const UniIdentity& paramDefUid, 
            std::vector<OwnerPtr<IParameterValueStorage>>& values) const override {}

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    protected:
        IDocument* GetDocument() const;
        ElementId GetOwnerElementId() const;

    private:
        WeakPtr<IElement> m_pOwnerElement;
    };

    // 控制点行为
    class StructureSlopeLinePositionPoints : public NdbObjectSchematic, public IElementPositionPoints
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, StructureSlopeLinePositionPoints, gcmp::NdbObjectSchematic, B66F80C3 - 3092 - 481B - 9774 - 1EF3FA4648CD, gmstructure, gcmp::IElementPositionPoints)
            DATA_TRANSIENT(IElement*, pOwnerElement)
        DBOBJECT_DATA_END
    public:
        explicit StructureSlopeLinePositionPoints(IElement* pOwnerElement);

        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }

        virtual int GetControlPointCount() const override;
        Vector3d GetControlPoint(int pointIndex) const override;
        void SetControlPoint(int pointIndex, const Vector3d& pos) override;

        virtual RegenDataId GetControlPointRdId(int pointIndex) const override;
        virtual void MarkControlPointRdId(int pointIndex) override;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    protected:
        int GetControlPointRegenDataName() const;
        IDocument* GetDocument() const;
        ElementId GetOwnerElementId() const;
    };

    // 控制点类型
    enum class SlopeLineGripPointType : int8_t
    {
        Start = 0, // 水平向起点
        End = 1,  // 水平向终点
    };

    // 辅助对象创建行为
    class StructureSlopeLineUiManipulatorComponent : public NdbObjectSchematic, public IElementUiManipulatorComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, StructureSlopeLineUiManipulatorComponent, gcmp::NdbObjectSchematic, F790177C - 72FE - 4D17 - 8599 - 077295DBAF49, gmstructure, IElementUiManipulatorComponent)
        DBOBJECT_DATA_END
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
    private:
        IElement* m_pOwnerElement;
    };

    // 夹点位置更新行为
    class GM_STRUCTURE_EXPORT StructureSlopeLineGripPointBehavior :public NdbObjectSchematic, public IElementShapeHandleBehavior
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, StructureSlopeLineGripPointBehavior, gcmp::NdbObjectSchematic, C8BB1AD3 - 9BEC - 4277 - BA21 - 28CB7E5D3E70, gmstructure, gcmp::IElementShapeHandleBehavior)
            DATA(IDocument*, Document)
            DATA(ElementId, ModelViewId)    //表示这个夹点在哪个视图上显示的(切换视图夹点会刷新)
            DATA(ElementId, ElementShapeHandleId)
            DBOBJECT_DATA_END

    public:
        static OwnerPtr<IElementShapeHandleBehavior> Create(IDocument* pDoc, const ElementId& modelViewId);
        virtual ~StructureSlopeLineGripPointBehavior() {}

    public:
        virtual IDocument* GetDocument() const override { return GetDocument__(); }
        void SetDocument(const IDocument* pDoc) { SetDocument__(pDoc); }

        virtual ElementId GetModelViewId() const override { return GetModelViewId__(); }
        void SetModelViewId(const ElementId& modelViewId) { SetModelViewId__(modelViewId); }

        virtual ElementId GetElementShapeHandleId() const override { return GetElementShapeHandleId__(); }
        virtual void SetElementShapeHandleId(const ElementId& id) override { return SetElementShapeHandleId__(id); }

        virtual void GetCalculators(ICalculatorCollection* calculators) const override;
        virtual bool Translate(const IElementMoveContext& moveContext) override;

        virtual OwnerPtr<IGraphicsElementShape> CreateGrahicsElementShapeInModelView(const IModelView* pModelView) const override;
        virtual void ReportParents(IElementParentReporter& reporter) const override;

        virtual void UpdatePosition() override;
        virtual void UpdatePositionIndexInMasterElement() override {};

        virtual void GetNearestPoint(Vector3d& nearPoint) const override;

        virtual bool FinishEditing() override { return false; }
        virtual bool GetHandleCommandString(const IObject* commandEnvironment, std::wstring& commandStr, CommandParameters& cmdParams) const override;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        StructureSlopeLineGripPointBehavior(IDocument* pDoc, const ElementId& modelViewId);
        IElementShapeHandle* GetElementShapeHandle() const;
        IElement* GetMasterElement() const;
    };
    
}// namespace gcmp
